package com.arcvideo.acsplayer.mode;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;

import android.database.Cursor;

import com.google.gson.annotations.SerializedName;

/**
 * @author guowei model 下面的类不能被混淆，并且所有的model 需要继承这个类 model 中变量名称需要和json 数据的名称一致
 */

public abstract class BaseModel implements Serializable {

	public BaseModel(JSONObject json) {
		CopyValue(getClass(), this, json);
	}

	public BaseModel() {

	}

	/**
	 * @param cursor
	 *            cursor 可以直接生成model
	 */

	public BaseModel(Cursor cursor) {

	}

	/**
	 * 可以重载处理自定义的类型，否则走默认的逻辑处理 对于未知的数据类型或者没有覆盖的数据类型要求自己实现赋值方法
	 */

	protected void UnKnownType(Class<?> type, Object object, Object json) {

	}

	/**
	 * 类实例数据copy
	 */

	private void CopyValue(Class<?> classType, BaseModel object, JSONObject json) {
		Field[] fields = classType.getFields();
		for (Field field : fields) {
			if (excludeField(field)) {
				continue;
			}
			String name = getFieldName(field);
			Class<?> type = field.getType();
			field.setAccessible(true);
			try {
				if (type.equals(int.class)) {
					int value = json.optInt(name);
					field.setInt(object, value);
				} else if (type.equals(long.class)) {
					long value = json.optLong(name);
					field.setLong(object, value);
				} else if (type.equals(byte.class)) {
					byte value = (byte) json.optInt(name);
					field.setByte(object, value);
				} else if (type.equals(float.class)) {
					float value = (float) json.optDouble(name);
					field.setFloat(object, value);
				} else if (type.equals(double.class)) {
					double value = json.optDouble(name);
					field.setDouble(object, value);
				} else if (type.equals(boolean.class)) {
					boolean value = json.optBoolean(name);
					field.setBoolean(object, value);
				} else if (type.equals(char.class)) {
					char value = (char) json.optInt(name);
					field.setChar(object, value);
				} else if (type.equals(short.class)) {
					short value = (short) json.optInt(name);
					field.setShort(object, value);
				} else if (type.equals(String.class)) {
					String value = json.optString(name);
					field.set(object, value);
				} else {
					Object value = json.opt(name);
					if (value != null) {
						if (value instanceof JSONObject) {
							Class<?> newclass = field.getType();
							if (BaseModel.class.isAssignableFrom(newclass)) {
								Constructor<?> cons = newclass.getConstructor(JSONObject.class);
								BaseModel model = (BaseModel) cons.newInstance(value);
								field.set(object, model);
							} else {
								UnKnownType(field.getType(), field.get(object), value);
							}
						} else if (value instanceof JSONArray) {
							List<BaseModel> modelList = parseJsonArrayToList(type, field, (JSONArray) value);
							if (modelList != null) {
								field.set(object, modelList);
							} else {
								UnKnownType(field.getType(), field.get(object), value);
							}
						} else {
							UnKnownType(field.getType(), field.get(object), value);
						}
					}

				}
			} catch (IllegalAccessException exception) {
				exception.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		// Log.d("zj", "object: " + object);
	}

	/**
	 * 将jsonArray中的数据解析到list中
	 *
	 * @param type
	 * @param field
	 * @param jsonArray
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private List<BaseModel> parseJsonArrayToList(Class<?> type, Field field, JSONArray jsonArray) {
		try {
			if (type instanceof Class && List.class.isAssignableFrom(type)) {
				Type type1 = field.getGenericType();
				if (type1 instanceof ParameterizedType) {
					Type[] args = ((ParameterizedType) type1).getActualTypeArguments();
					Class<?> newclass = (Class<?>) args[0];
					if (BaseModel.class.isAssignableFrom(newclass)) {
						List<BaseModel> list = (List<BaseModel>) ((Class<?>) type).newInstance();
						for (int i = 0; i < jsonArray.length(); i++) {
							Constructor<?> cons = newclass.getConstructor(JSONObject.class);
							BaseModel model = (BaseModel) cons.newInstance(jsonArray.optJSONObject(i));
							list.add(model);
						}
						return list;
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 拿到字段名称，可以设置别名
	 *
	 * @param f
	 * @return
	 */
	private String getFieldName(Field f) {
		SerializedName serializedName = f.getAnnotation(SerializedName.class);
		return serializedName == null ? f.getName() : serializedName.value();
	}

	/**
	 * 是否需要过滤掉该字段
	 *
	 * @param f
	 * @return
	 */
	protected boolean excludeField(Field f) {
		int modifiers = f.getModifiers();
		if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
			return true;
		}
		return false;
	}

}